package pe.com.bbva.carga.bo.impl;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import pe.com.bbva.carga.bo.ProcesoCargaBO;
import pe.com.bbva.carga.bo.UploadClassTargpsBO;
import pe.com.bbva.carga.domain.ProcesoCarga;
import pe.com.bbva.mantenimiento.bo.BinBO;
import pe.com.bbva.mantenimiento.bo.KitBO;
import pe.com.bbva.mantenimiento.bo.KitMaterialBO;
import pe.com.bbva.mantenimiento.bo.ParametroBO;
import pe.com.bbva.mantenimiento.bo.ProveedorBO;
import pe.com.bbva.mantenimiento.bo.TablaBO;
import pe.com.bbva.mantenimiento.bo.TipoTarjetaBO;
import pe.com.bbva.mantenimiento.domain.Bin;
import pe.com.bbva.mantenimiento.domain.Kit;
import pe.com.bbva.mantenimiento.domain.KitMaterial;
import pe.com.bbva.mantenimiento.domain.Parametro;
import pe.com.bbva.mantenimiento.domain.Proveedor;
import pe.com.bbva.mantenimiento.domain.Tabla;
import pe.com.bbva.mantenimiento.domain.TipoTarjeta;
import pe.com.bbva.targps.bo.TarjetaBO;
import pe.com.bbva.targps.domain.Tarjeta;
import pe.com.bbva.util.Constantes;
import pe.com.bbva.util.Util;
import pe.com.stefanini.core.domain.UsuarioSession;

@Service("uploadClassTargpsBOImpl")
public class UploadClassTargpsBOImpl implements UploadClassTargpsBO {
	Logger logger = Logger.getLogger(this.getClass());
	
	@Resource
	private TarjetaBO tarjetaBO;
	
	@Resource
	private TablaBO tablaBO;
	
	@Resource
	private KitBO kitBO;
	
	@Resource
	private KitMaterialBO kitMaterialBO;
	
	@Resource
	private ParametroBO parametroBO;
	
	@Resource
	private ProcesoCargaBO procesoCargaBO;
	
	@Resource
	private BinBO binBO;
	
	@Resource
	private ProveedorBO proveedorBO;
	
	@Resource
	private TipoTarjetaBO tipoTarjetaBO;

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void procesarTarjetas(List<Tarjeta> tarjetas, boolean permitir, UsuarioSession usuario) {
		try{
			int facturado = 0;
			String nomArchivo = Util.getArchivoGPSCompleto(new Date());
			StringBuffer content = new StringBuffer();
			int numCabecera = 0;
			
			HashMap<ProcesoCarga, List<Tarjeta>> map = new HashMap<ProcesoCarga, List<Tarjeta>>();
			List<Tarjeta> tarjetasTmp = new ArrayList<Tarjeta>();
			List<ProcesoCarga> procesosTmp = new ArrayList<ProcesoCarga>();
			
			ProcesoCarga procesoOrden=null;
			for(Tarjeta tarjeta:tarjetas){
				if(procesoOrden == null || !procesoOrden.getId().equals(tarjeta.getIdProcesoCarga())){
					procesoOrden = procesoCargaBO.findById(tarjeta.getIdProcesoCarga());
					procesosTmp.add(procesoOrden);
				}
			}
			
			for(ProcesoCarga procesoTmp: procesosTmp){
				for(Tarjeta tarjetaTmp: tarjetas){
					if(tarjetaTmp.getIdProcesoCarga().equals(procesoTmp.getId())){
						tarjetasTmp.add(tarjetaTmp);
					}
				}
				map.put(procesoTmp, tarjetasTmp);
			}
			Long idProveedor = Long.valueOf(parametroBO.findById(Constantes.PROVEEDOR_DEFAULT).getValor());
			Proveedor proveedor = proveedorBO.findById(idProveedor);
			String numeral = parametroBO.findById(Constantes.NUMERAL_CABECERA).getValor();
			String tipoRegistro = parametroBO.findById(Constantes.TIPO_REGISTRO).getValor();
			String tipoInterfaz = parametroBO.findById(Constantes.TIPO_INTERFAZ).getValor();
			String paisGPS = parametroBO.findById(Constantes.PAIS_GPS).getValor();
			String identificadorInterfaz = parametroBO.findById(Constantes.IDENTIFICADOR_INTERFAZ).getValor();
			String nombreFichero = parametroBO.findById(Constantes.NOMBRE_FICHERO).getValor();
			String nomFichero = StringUtils.leftPad(nombreFichero, 40, " ");
			String fechaEjecucion = Util.getArchivoGPSCompleto(new Date());
			String cabecera = numeral + tipoRegistro + tipoInterfaz + paisGPS + identificadorInterfaz + nomFichero + fechaEjecucion;
			content.append(cabecera + "\n");
			
			String centroCosteOriginal = parametroBO.findById(Constantes.CENTRO_COSTE_ORIGINAL).getValor();
			String materialAntiguo =  parametroBO.findById(Constantes.MATERIAL_ANTIGUO).getValor();
			String prefijoCoste = parametroBO.findById(Constantes.PREFIJO_COSTE).getValor();
			String identificadorRegistro = parametroBO.findById(Constantes.ID_IDENTIFICADOR_REGISTRO).getValor();
			String unidadMedida = parametroBO.findById(Constantes.UNIDAD_MEDIDA).getValor();
			
			String fechaFinal = "";
			Iterator itr = map.entrySet().iterator();
			int encarte = 0;
			int manipulado = 0;
			int inicio = 1;
			while (itr.hasNext()) {
				Map.Entry e = (Map.Entry)itr.next();
				ProcesoCarga proceso = (ProcesoCarga) e.getKey();
				List<Tarjeta> tarjetasFacturacion = (List<Tarjeta>) e.getValue();
				if(proceso.getEstadoFacturacion().equals(String.valueOf(Constantes.ESTADO_PROCESO_NO_FACTURADO))){
					for(Tarjeta tarjeta: tarjetasFacturacion){
						if(!permitir && tarjeta.getEstadoFacturacion().equals(String.valueOf(Constantes.ESTADO_PROCESO_FACTURADO))){
							continue;
						}else{
							tarjeta.setEstadoFacturacion(String.valueOf(Constantes.ESTADO_PROCESO_NO_FACTURADO));
						}
						if(tarjeta.getEstado().equals(String.valueOf(Constantes.ESTADO_TARJETA_ENTREGADO)) && 
							tarjeta.getEstadoFacturacion().equals(String.valueOf(Constantes.ESTADO_PROCESO_NO_FACTURADO)))
						{
							if(inicio==1){
								fechaFinal = Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
							}
							String correlativo = Util.addValueToLeft(String.valueOf(inicio), 6, "0");
							
							String binCod = String.valueOf(Long.valueOf(tarjeta.getNumTarjeta())).substring(0,8); 
							Bin binBusc = new Bin();
							binBusc.setCodigo(binCod);
							Bin bin = binBO.findBins(binBusc).get(0);
							
							Tabla busc = new Tabla();
							busc.setPadre(tablaBO.findById(Constantes.ID_TABLA_COD_TARJETA));
							busc.setCodigo(tarjeta.getCodTarjeta());
							Tabla codTarjeta = tablaBO.findTablas(busc).get(0);
							
							busc = new Tabla();
							busc.setPadre(tablaBO.findById(Constantes.ID_TABLA_TAMANIO));
							busc.setCodigo(tarjeta.getTamanio());
							Tabla tamTarjeta = tablaBO.findTablas(busc).get(0);
							
							TipoTarjeta tipTarBusc = new TipoTarjeta();
							tipTarBusc.setBin(bin);
							tipTarBusc.setCodTarjeta(codTarjeta);
							tipTarBusc.setTamTarjeta(tamTarjeta);
							TipoTarjeta tipoTarjeta = tipoTarjetaBO.findTipos(tipTarBusc).get(0);
							
							Kit kitBusc = new Kit();
							kitBusc.setTipoTarjeta(tipoTarjeta);
							Kit kit = kitBO.findKits(kitBusc).get(0);
							KitMaterial materialBusc = new KitMaterial();
							materialBusc.setKit(kit);
							List<KitMaterial> materiales = kitMaterialBO.findKits(materialBusc);
							
							for(KitMaterial material: materiales){
								Tabla tablaBuscar = new Tabla();
								tablaBuscar.setCodigo(tarjeta.getTipoSolicitud());
								tablaBuscar.setPadre(tablaBO.findById(Constantes.ID_TABLA_TIPO_SOLICITUD));
								Tabla solicitud = tablaBO.findTablas(tablaBuscar).get(0);
								
								if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_PRODPERS)){
									String linea =  correlativo + identificadorRegistro + Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion()) +
													Util.addValueToLeft(String.valueOf(kit.getCodGPS()), 18, " ") + 
													Util.addValueToLeft(String.valueOf(material.getCantidad()), 10, "0") + unidadMedida +
													solicitud.getAbreviado() + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
													tarjeta.getOficina() + materialAntiguo + centroCosteOriginal + prefijoCoste + 
													Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
									content.append(linea + "\n");
								}
								if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_PRODUCCION)){
									String linea =  correlativo + identificadorRegistro + Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion()) +
									Util.addValueToLeft(String.valueOf(kit.getCodGPS()), 18, " ") + 
									Util.addValueToLeft(String.valueOf(material.getCantidad()), 10, "0") + unidadMedida +
									solicitud.getAbreviado() + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
									tarjeta.getOficina() + materialAntiguo + centroCosteOriginal + prefijoCoste + 
									Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
									content.append(linea + "\n");
								}
								if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_PERSONALIZACION)){
									String linea =  correlativo + identificadorRegistro + Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion()) +
									Util.addValueToLeft(String.valueOf(kit.getCodGPS()), 18, " ") + 
									Util.addValueToLeft(String.valueOf(material.getCantidad()), 10, "0") + unidadMedida +
									solicitud.getAbreviado() + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
									tarjeta.getOficina() + materialAntiguo + centroCosteOriginal + prefijoCoste + 
									Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
									content.append(linea + "\n");
								}
								if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_ENCARTE))
								{
									encarte += material.getCantidad();
								}
								if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_MANIPULADO)){
									manipulado += material.getCantidad();
								}
							}
							tarjeta.setEstadoFacturacion(String.valueOf(Constantes.ESTADO_PROCESO_FACTURADO));
							tarjetaBO.save(tarjeta);
							inicio ++;
						}
					}
					procesoCargaBO.cambiaFacturado(proceso, usuario);
					facturado++;
				}
			}
			if(facturado!=0){
				Tabla manipuladoGPS = tablaBO.findById(Constantes.ID_TABLA_MANIPULADO);
				Tabla encarteGPS = tablaBO.findById(Constantes.ID_TABLA_ENCARTE);
				
				String correlativo = Util.addValueToLeft(String.valueOf(inicio), 6, "0"); 
				
				String lineaManipulado =  correlativo + identificadorRegistro + fechaFinal +
				Util.addValueToLeft(manipuladoGPS.getAbreviado(), 18, " ") + 
				Util.addValueToLeft(String.valueOf(manipulado), 10, "0") + unidadMedida +
				"   " + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
				"       " + materialAntiguo + centroCosteOriginal + prefijoCoste + fechaFinal;
				inicio++;
				
				String lineaEncarte =  correlativo + identificadorRegistro + fechaFinal +
				Util.addValueToLeft(encarteGPS.getAbreviado(), 18, " ") + 
				Util.addValueToLeft(String.valueOf(encarte), 10, "0") + unidadMedida +
				"   " + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
				"       " + materialAntiguo + centroCosteOriginal + prefijoCoste + fechaFinal;
				inicio++;
				
				Parametro parametro = parametroBO.findById(Constantes.PARAMETRO_RUTA_GPS);
				File file = new File(parametro.getValor());
				if(!file.exists())
					file.mkdir();
				FileWriter fw = new FileWriter(parametro.getValor()+"/"+nomArchivo+".txt");
				BufferedWriter bw = new BufferedWriter(fw);
				int numTotal = numCabecera + inicio + 2;
				inicio += 2;
				String pie = String.format("%06d",numTotal) + "9" + String.format("%05d",numCabecera) + String.format("%05d",inicio) + "00000";
				content.append(lineaManipulado + "\n");
				content.append(lineaEncarte + "\n");
				content.append(pie);
				bw.write(content.toString());
				bw.close();
			}
		}
		catch(Exception e){
			e.getStackTrace();
		}
	}
	
	public void procesarArchivos(List<ProcesoCarga> procesos, UsuarioSession usuario) {
		try{
			int facturado = 0;
			String nomArchivo = Util.getArchivoGPSCompleto(new Date());
			StringBuffer content = new StringBuffer();
			int numCabecera = 1;
			int inicio = 1;
			int encarte = 0;
			int manipulado = 0;
			
			Long idProveedor = Long.valueOf(parametroBO.findById(Constantes.PROVEEDOR_DEFAULT).getValor());
			Proveedor proveedor = proveedorBO.findById(idProveedor);
			String numeral = parametroBO.findById(Constantes.NUMERAL_CABECERA).getValor();
			String tipoRegistro = parametroBO.findById(Constantes.TIPO_REGISTRO).getValor();
			String tipoInterfaz = parametroBO.findById(Constantes.TIPO_INTERFAZ).getValor();
			String paisGPS = parametroBO.findById(Constantes.PAIS_GPS).getValor();
			String identificadorInterfaz = parametroBO.findById(Constantes.IDENTIFICADOR_INTERFAZ).getValor();
			String nombreFichero = parametroBO.findById(Constantes.NOMBRE_FICHERO).getValor();
			String nomFichero = StringUtils.leftPad(nombreFichero, 40, " ");
			String fechaEjecucion = Util.getArchivoGPSCompleto(new Date());
			String cabecera = numeral + tipoRegistro + tipoInterfaz + paisGPS + identificadorInterfaz + nomFichero + fechaEjecucion;
			content.append(cabecera + "\n");
			
			String centroCosteOriginal = parametroBO.findById(Constantes.CENTRO_COSTE_ORIGINAL).getValor();
			String materialAntiguo =  parametroBO.findById(Constantes.MATERIAL_ANTIGUO).getValor();
			String prefijoCoste = parametroBO.findById(Constantes.PREFIJO_COSTE).getValor();
			String identificadorRegistro = parametroBO.findById(Constantes.ID_IDENTIFICADOR_REGISTRO).getValor();
			String unidadMedida = parametroBO.findById(Constantes.UNIDAD_MEDIDA).getValor();		
			String fechaFinal = "";
			
			for(ProcesoCarga proceso:procesos){
				if(proceso.getEstadoFacturacion().equals(String.valueOf(Constantes.ESTADO_PROCESO_NO_FACTURADO))){
					Kit kitBusc = new Kit();
					kitBusc.setEstado("1");
					List<Kit> kits = kitBO.findKits(kitBusc);
					for(Kit kit: kits){
						String correlativo = Util.addValueToLeft(String.valueOf(inicio), 6, "0");
						
						KitMaterial materialBusc = new KitMaterial();
						materialBusc.setKit(kit);
						List<KitMaterial> materiales = kitMaterialBO.findKits(materialBusc);

						Tarjeta tarjetaBuscar = new Tarjeta();
						tarjetaBuscar.setIdProcesoCarga(proceso.getId());
						tarjetaBuscar.setBin(kit.getTipoTarjeta().getBin().getCodigo());
						tarjetaBuscar.setTamanio(kit.getTipoTarjeta().getTamTarjeta().getCodigo());
						tarjetaBuscar.setCodTarjeta(kit.getTipoTarjeta().getCodTarjeta().getCodigo());
						List<Tarjeta> tarjetas = tarjetaBO.findTarjetas(tarjetaBuscar);
						
						for(Tarjeta tarjeta:tarjetas){
							if(tarjeta.getEstado().equals(String.valueOf(Constantes.ESTADO_TARJETA_ENTREGADO)) && 
								tarjeta.getEstadoFacturacion().equals(String.valueOf(Constantes.ESTADO_PROCESO_NO_FACTURADO)))
							{
								if(inicio==1){
									fechaFinal = Util.getFormatoFecha(tarjeta.getFechaEstampacion());
								}
								for(KitMaterial material: materiales){
									Tabla tablaBuscar = new Tabla();
									tablaBuscar.setCodigo(tarjeta.getTipoSolicitud());
									tablaBuscar.setPadre(tablaBO.findById(Constantes.ID_TABLA_TIPO_SOLICITUD));
									Tabla solicitud = tablaBO.findTablas(tablaBuscar).get(0);
									
									if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_PRODPERS)){
										String linea =  correlativo + identificadorRegistro + Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion()) +
														Util.addValueToLeft(String.valueOf(kit.getCodGPS()), 18, " ") + 
														Util.addValueToLeft(String.valueOf(material.getCantidad()), 10, "0") + unidadMedida +
														solicitud.getAbreviado() + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
														tarjeta.getOficina() + materialAntiguo + centroCosteOriginal + prefijoCoste + 
														Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
										content.append(linea + "\n");
									}
									if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_PRODUCCION)){
										String linea =  correlativo + identificadorRegistro + Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion()) +
										Util.addValueToLeft(String.valueOf(kit.getCodGPS()), 18, " ") + 
										Util.addValueToLeft(String.valueOf(material.getCantidad()), 10, "0") + unidadMedida +
										solicitud.getAbreviado() + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
										tarjeta.getOficina() + materialAntiguo + centroCosteOriginal + prefijoCoste + 
										Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
										content.append(linea + "\n");
									}
									if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_PERSONALIZACION)){
										String linea =  correlativo + identificadorRegistro + Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion()) +
										Util.addValueToLeft(String.valueOf(kit.getCodGPS()), 18, " ") + 
										Util.addValueToLeft(String.valueOf(material.getCantidad()), 10, "0") + unidadMedida +
										solicitud.getAbreviado() + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
										tarjeta.getOficina() + materialAntiguo + centroCosteOriginal + prefijoCoste + 
										Util.getArchivoGPSFecha(tarjeta.getFechaEstampacion());
										content.append(linea + "\n");
									}
									if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_ENCARTE))
									{
										encarte += material.getCantidad();
									}
									if(material.getTipoMaterial().getId().equals(Constantes.ID_TABLA_MANIPULADO)){
										manipulado += material.getCantidad();
									}
								}
								tarjeta.setEstadoFacturacion(String.valueOf(Constantes.ESTADO_PROCESO_FACTURADO));
								tarjetaBO.save(tarjeta);
								inicio ++;
							}
						}
					}
					procesoCargaBO.cambiaFacturado(proceso, usuario);
					facturado++;
				}
			}
			if(facturado!=0){
				Tabla manipuladoGPS = tablaBO.findById(Constantes.ID_TABLA_MANIPULADO);
				Tabla encarteGPS = tablaBO.findById(Constantes.ID_TABLA_ENCARTE);
				
				String correlativo = Util.addValueToLeft(String.valueOf(inicio), 6, "0"); 
				
				String lineaManipulado =  correlativo + identificadorRegistro + fechaFinal +
				Util.addValueToLeft(manipuladoGPS.getAbreviado(), 18, " ") + 
				Util.addValueToLeft(String.valueOf(manipulado), 10, "0") + unidadMedida +
				"   " + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
				"       " + materialAntiguo + centroCosteOriginal + prefijoCoste + fechaFinal;
				inicio++;
				
				String lineaEncarte =  correlativo + identificadorRegistro + fechaFinal +
				Util.addValueToLeft(encarteGPS.getAbreviado(), 18, " ") + 
				Util.addValueToLeft(String.valueOf(encarte), 10, "0") + unidadMedida +
				"   " + Util.addValueToLeft(String.valueOf(proveedor.getCodigoGPS()), 10, "0") +
				"       " + materialAntiguo + centroCosteOriginal + prefijoCoste + fechaFinal;
				inicio++;
				
				Parametro parametro = parametroBO.findById(Constantes.PARAMETRO_RUTA_GPS);
				File file = new File(parametro.getValor());
				if(!file.exists())
					file.mkdir();
				FileWriter fw = new FileWriter(parametro.getValor()+"/"+nomArchivo+".txt");
				BufferedWriter bw = new BufferedWriter(fw);
				int numTotal = numCabecera + inicio + 2;
				inicio += 2;
				String pie = String.format("%06d",numTotal) + "9" + String.format("%05d",numCabecera) + String.format("%05d",inicio) + "00000";
				content.append(lineaManipulado + "\n");
				content.append(lineaEncarte + "\n");
				content.append(pie);
				bw.write(content.toString());
				bw.close();
			}
		}
		catch(Exception e){
			e.getStackTrace();
		}
	}
}